﻿using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class SimpleState
{
    [SerializeField]
    public string stateName;
    Action onenter;
    Action<float> onupdate;
    Action onleave;
    bool isEntered;
    bool isLeaved;
    public SimpleState()
    {
    }

    public SimpleState(string _s)
    {
        stateName = _s;
    }

    public virtual void SetAction(Action _onenter = null, Action<float> _onupdate = null, Action _onleave = null)
    {
        onenter = _onenter;
        onupdate = _onupdate;
        onleave = _onleave;
    }

    public void BindEvent(Action _onenter = null, Action _onleave = null, Action<float> _onupdate = null)
    {
        if (_onenter != null)
            onenter += _onenter;
        if (_onleave != null)
            onleave += _onleave;
        if (_onupdate != null)
            onupdate += _onupdate;
    }

    public virtual void OnLeave()
    {
        if (onleave != null)
        {
            onleave();
        }
    }

    public virtual void OnEnter()
    {
        if (onenter != null)
            onenter();
    }

    public virtual void OnUpdate(float dt)
    {
        if (onupdate != null)
            onupdate(dt);
    }
}

[Serializable]
public class SimpleFSM
{
    /// <summary>
    /// 所有状态
    /// </summary>
    Dictionary<string, SimpleState> _states = new Dictionary<string, SimpleState>();
    public float stateTime;
    public float pauseTime;
    bool isPause;

    [SerializeField]
    SimpleState _currentState;
    [SerializeField]
    SimpleState _lastCurrentState;

    SimpleState currentState
    {
        get
        {
            return _currentState;
        }
        set
        {
            if (_currentState != null)
            {
                _lastCurrentState = _currentState;
                _currentState.OnLeave();
            }
            stateTime = 0;
            _currentState = value;
            _currentState.OnEnter();
        }
    }


    #region Interface

    /// <summary>
    /// 更新状态
    /// </summary>
    /// <param name="dt">Dt.</param>
    public void UpdateState(float dt)
    {
        if (isPause)
        {
            pauseTime += dt;
            return;
        }

        if (_currentState != null)
        {
            stateTime += dt;
            _currentState.OnUpdate(dt);
        }
    }

    /// <summary>
    /// 暂停
    /// </summary>
    public void Pause()
    {
        pauseTime = 0;
        isPause = true;
    }

    /// <summary>
    /// 恢复暂停
    /// </summary>
    public void Recove()
    {
        isPause = false;
    }

    /// <summary>
    /// 获取当前状态
    /// </summary>
    /// <returns>The current state.</returns>
    public SimpleState GetCurrentState()
    {
        return currentState;
    }

    /// <summary>
    /// 获取上个状态
    /// </summary>
    /// <returns>The last state.</returns>
    public SimpleState GetLastState()
    {
        return _lastCurrentState;
    }


    /// <summary>
    /// 设置状态
    /// </summary>
    /// <param name="sateName"></param>
    public void SetState(string sateName)
    {
        if (_states.TryGetValue(sateName, out var simpleState))
        {
            SetState(simpleState);
        }
    }

    /// <summary>
    /// 设置状态
    /// </summary>
    /// <param name="state">State.</param>
    public void SetState(SimpleState state,bool forceReEnter = false)
    {
        if (!forceReEnter && IsState(state))
            return;

        currentState = state;
    }

    /// <summary>
    /// 添加状态
    /// </summary>
    /// <param name="_s">S.</param>
    /// <param name="_onEnter">On enter.</param>
    /// <param name="_onUpdate">On update.</param>
    /// <param name="_onExit">On exit.</param>
    public SimpleState AddState(SimpleState _s, Action _onEnter = null, Action<float> _onUpdate = null, Action _onExit = null)
    {
        if (_states.ContainsKey(_s.stateName))
            return _states[_s.stateName];

        _s.SetAction(_onEnter, _onUpdate, _onExit);
        _states.Add(_s.stateName, _s);
        return _s;
    }

    public T AddState<T>(Action _onEnter = null, Action<float> _onUpdate = null, Action _onExit = null) where T : SimpleState, new()
    {
        T t = new T();
        t.stateName = typeof(T).ToString();
        AddState(t, _onEnter, _onUpdate, _onExit);
        return t;
    }

    /// <summary>
    /// 当前是否为改状态
    /// </summary>
    /// <returns><c>true</c> if this instance is state the specified _s; otherwise, <c>false</c>.</returns>
    /// <param name="_s">S.</param>
    public bool IsState(SimpleState _s)
    {
        if (_s == null)
            return false;

        if (currentState != null && currentState.stateName == _s.stateName)
            return true;

        return false;
    }

    /// <summary>
    /// 刷新状态时间
    /// </summary>
    public void RefreshStateTime()
    {
        stateTime = 0;
    }

    #endregion

}
